home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-28 | 20.6 KB | 740 lines | [TEXT/MPS ] |
- /*
- File: 2020Recipient.cp
-
- Copyright: © 1991-1994 by Apple Computer, Inc.
- All rights reserved.
-
- Part of the AOCE Sample SMSAM Package. Consult the license
- which came with this software for your specific legal rights.
-
- */
-
-
-
- #ifndef __BLJSTANDARDINCLUDES__
- #include "BLJStandardIncludes.h"
- #endif
-
- #ifndef __AYSTHREADGLUE__
- #include "AYSThreadGlue.h"
- #endif
-
- #ifndef __2020RECIPIENT__
- #include "2020Recipient.h"
- #endif
-
- #ifndef __2020HALFGATEWAY__
- #include "2020HalfGateway.h"
- #endif
-
- #ifndef __BLJOCEUTILITIES__
- #include "BLJOCEUtilities.h"
- #endif
-
- #ifndef __OCEERRORS__
- #include <OCEErrors.h>
- #endif
-
- #ifndef __UTILITIES__
- #include "Utilities.h"
- #endif
-
- #ifndef __DEBUGGINGGEAR__
- #include "DebuggingGear.h"
- #endif
-
- #ifndef __DEBUGASSERT__
- #include "DebugAssert.h"
- #endif
-
- #ifndef __2020LETTER__
- #include "2020Letter.h"
- #endif
-
- #pragma segment T2020Recipient
-
- /***********************************|****************************************/
-
- #if 0
- Boolean ConvertDNodeToPackedPathName ( const RLI* aRLI, PackedPathName* packedPathPtr, unsigned short packedPathPtrSize, AuthIdentity identity )
- {
- if ( aRLI && ( aRLI->dNodeNumber != kNULLDNodeNumber ) )
- {
- DirMapDNodeNumberToPathNamePB pb;
-
- memset (&pb, 0, sizeof(pb));
-
- pb.identity = identity;
- pb.directoryName = aRLI->directoryName;
- pb.discriminator = aRLI->discriminator;
- pb.dNodeNumber = aRLI->dNodeNumber;
- pb.path = packedPathPtr;
- pb.lengthOfPathName = (unsigned short) packedPathPtrSize;
-
- OSErr err = DirMapDNodeNumberToPathName((DirParamBlockPtr) &pb, false);
-
- const char * GetErrorText ( OSErr err );
- if ( err != noErr )
- keith << "T2020Recipient, ConvertDNodeToPackedPathName, err=" << err << " " << GetErrorName ( err ) << endl << flush;
-
- return err == noErr;
- }
-
- return false;
- }
- #endif
-
- /***********************************|****************************************/
-
- T2020Recipient::T2020Recipient(T2020Letter* owningLetter, const OCEPackedRecipient *recipient, unsigned short originalRecipientIndex, Boolean responsible, Boolean marked) :
- fOwningLetter(owningLetter),
- fRecipient ( (PackedDSSpec*) recipient ),
- fResponsible ( responsible ),
- fOriginalRecipientIndex ( originalRecipientIndex ),
- fResolvedRecipientIndex ( 0 ),
- fStatus ( cUnknown ),
- fCheckedWhetherPathInformationIsOptional ( false ),
- fIsPathInfoOptional ( false ),
- fCheckedWhetherRecipientNameIsUnique ( false ),
- fRecipientNameIsUnique ( false )
- {
- #if false
- keith << "OCEPackedRecipient structure is " << endl;
- DumpHex (keith, (char *) recipient, recipient->dataLength + sizeof(OCEPackedRecipient)); keith << endl;
- #endif
-
- ASSERT_RETURN ( recipient != nil );
-
-
-
- #if 0
-
- const unsigned long recipientPhysicalLength = recipient->dataLength + sizeof ( ProtoOCEPackedRecipient );
- ASSERT_RETURN ( recipientPhysicalLength <= kOCEPackedRecipientMaxBytes );
- fOCEPackedRecipient = (OCEPackedRecipient*) FAILNewPtr ( recipientPhysicalLength );
- BlockMove ( recipient, fOCEPackedRecipient, recipientPhysicalLength );
-
- fRecordID = (RecordIDPtr) FAILNewPtr(sizeof(*fRecordID));
- fOCERecipient.entitySpecifier = fRecordID;
- OCEUnpackRecipient (fOCEPackedRecipient, &fOCERecipient, fOCERecipient.entitySpecifier);
-
- #if debug
- if (OCEValidPackedRLI(fRecordID->rli) == false) {
- keith << "*** T2020Recipient:T2020Recipient, ValidPackedRLI(rli) FAILED, continuing." << endl << flush;
- }
- #endif
-
- fRLI = (RLI*) FAILNewPtr ( fRecordID->rli->dataLength + sizeof ( ProtoPackedRLI ) );
- OCEUnpackRLI ( fRecordID->rli, fRLI );
-
- // OK. Now, we either have a dNodeNumber in this address (in which case we need to
- // generate the packed path to accompany it), or we've got the packed path (in
- // which case we need to figure out it's dNodeNumber.) We postpone getting the dNodeNumber
- // from the packed path until it's actually asked for (because it won't be used most of the
- // time).
-
- if (fRLI->dNodeNumber != kNULLDNodeNumber)
- {
- #if 1
- TPathName pathName;
- fOwningLetter-> GetHalfGateway()->FindPathNameForDNode ( fRLI->dNodeNumber,
- TDirectory ( fRLI->directoryName, fRLI-> discriminator ),
- pathName );
- fPackedPathNamePtr = (PackedPathNamePtr) FAILNewPtr ( (( const PackedPathName*) pathName)->dataLength + sizeof(ProtoPackedPathName) );
- FAILOSErr ( OCECopyPackedPathName ( (const PackedPathName*) pathName, fPackedPathNamePtr, GetPtrSize ( (Ptr) fPackedPathNamePtr) ) );
-
- #else
-
- PackedPathName tempPathName;
-
- if ( ConvertDNodeToPackedPathName ( fRLI, &tempPathName, sizeof ( tempPathName ), fOwningLetter->GetHalfGateway()->GetForwarderIdentity() ) )
- {
- const unsigned long pathNameSize = tempPathName.dataLength + sizeof ( ProtoPackedPathName );
- fPackedPathNamePtr = (PackedPathName*) FAILNewPtr ( pathNameSize );
- BlockMove ( &tempPathName, fPackedPathNamePtr, pathNameSize );
- }
- else
- fPackedPathNamePtr = nil;
-
- fRLI->path = fPackedPathNamePtr;
- fPathNameItems = nil;
- #endif
- }
-
- TRY
- if (fRLI->path)
- { if (OCEValidPackedPathName(fRLI->path))
- {
- fPathNameItemsCount = OCEDNodeNameCount(fRLI->path);
- fPathNameItems = (RStringPtr*) FAILNewPtr(sizeof(fPathNameItems[0]) * fPathNameItemsCount);
- if (fPathNameItems)
- OCEUnpackPathName (fRLI->path, fPathNameItems, fPathNameItemsCount);
- }
- else
- {
- keith << "[invalid path] " << flush;
- }
- }
-
- EXCEPTION
- PASSEXCEPTION();
-
- ENDEXCEPTION;
-
- #endif
-
- }
-
- /***********************************|****************************************/
-
- T2020Recipient::~T2020Recipient()
- {
- keithF ( 1, "T2020Recipient::~T2020Recipient, " << fRecipient );
-
- #if 0
- DisposeIfPtr ((Ptr) fPackedPathNamePtr);
- DisposeIfPtr ((Ptr) fPathNameItems);
- DisposeIfPtr ((Ptr) fRecordID);
- DisposeIfPtr ((Ptr) fRLI);
- DisposeIfPtr ((Ptr) fOCEPackedRecipient);
- #endif
- }
-
- /***********************************|****************************************/
-
- #if 0
-
- /***********************************|****************************************/
-
- Boolean IsRecordIsUserAliasRecord ( const TRecord& record )
- {
- return false;
- }
-
- /***********************************|****************************************/
-
- PackedDSSpecHandle FAILNewDSSpecHandle ( const DSSpec* originalH )
- {
- PackedDSSpecHandle result = FAILNewHandle ( (**originalH).dataLength + sizeof ( ProtoPackedDSSpec ) );
- if ( result )
- {
- FAILOSErr ( OCECopyPackedDSSpec ( *originalH, *resultH, (**originalH).dataLength );
- }
-
- return result;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::Initialize ( )
- {
- // If the record is an alias, then we need to resolve the alias and
- // use the real record.
-
- if ( IsRecordIsUserAliasRecord ( fRecipient ) )
- {
- PackedDSSpecHandle dsSpecH = nil;
-
- TRY
- dsSpecH = FAILNewDSSpecHandle ( (const DSSpec*) fRecipient );
-
- if ( SDPResolveAliasFile( dsSpecH, GetOwningGateway()->GetForwarderIdentity(), false ) == noErr )
- {
- // Replace the recipient ( which is an alias ) with the original
- // record.
- HLock ( (Handle) dsSpecH );
- fRecipient = TDSSpec ( *dsSpecH );
- }
-
- EXCEPTION
-
- ENDEXCEPTION
-
- DisposeIfHandle ( (Handle) dsSpecH );
- }
-
- fInitialized = true;
- }
-
- #endif
-
- /***********************************|****************************************/
-
- #if 0
- Boolean ConvertPackedPathnameToDNode (RLI* aRLI, AuthIdentity identity) {
-
- if (aRLI && aRLI->path && (OCEIsNullPackedPathName(aRLI->path) == false)) {
- DirMapPathNameToDNodeNumberPB pb;
-
- memset (&pb, 0, sizeof(pb));
- pb.directoryName = aRLI->directoryName;
- pb.discriminator = aRLI->discriminator;
- pb.path = aRLI->path;
-
- OSErr err = DirMapPathNameToDNodeNumberSleep( (DirParamBlockPtr) &pb );
- if ( err == kOCEStreamCreationErr )
- err = DirMapPathNameToDNodeNumberSleep( (DirParamBlockPtr) &pb );
-
- #if debug
- if ( err )
- keithF ( 1, "ConvertPackedPathNameToDNode, err=" << err );
- #endif
-
- if (err == noErr) {
- aRLI->dNodeNumber = pb.dNodeNumber;
- }
- return (err == noErr);
- }
- return false;
- }
- #endif
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::GetResponsible () const
- {
- keithF ( 15, "T2020Recipient::Responsible(), " << fRecipient << ", result = " << (short) fResponsible );
-
- return fResponsible;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::GetRecipientName (TRString& name) const
- { Boolean result = false;
-
- #if old
- OCECopyRString (fOCERecipient.entitySpecifier->local.recordName, &name, kRStringMaxBytes);
- #else
- fRecipient.GetRecordName ( name );
- #endif
-
- keithF ( 15, "T2020Recipient::GetRecipientName() name=" << name );
-
- return ( name.GetLength() > 0 );
- }
-
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::GetRecipientType (TRString& type) const
- {
- #if 0
- OCECopyRString (fOCERecipient.entitySpecifier->local.recordType, &type, kRStringMaxBytes);
- #else
- fRecipient.GetRecordType ( type );
- #endif
-
- keithF ( 15, "T2020Recipient::GetRecipientType(), " << fRecipient << ", type=" << type );
-
- return ( type.GetLength() > 0 );
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::GetDirectoryName (DirectoryName& directoryName) const {
-
- TDirectory directory;
- fRecipient.GetDirectory ( directory );
- OCECopyRString ( directory.GetName(), (RStringPtr) &directoryName, kDirectoryNameMaxBytes );
-
- keithF ( 15, "T2020Recipient::GetDirectoryName(), " << fRecipient << ", dirName=" << directoryName );
-
- return ( directoryName.dataLength > 0 );
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::GetPathDNode (unsigned long& dNode) const
- {
- dNode = fRecipient.GetNode();
-
- return true;
- }
-
- /***********************************|****************************************/
-
- unsigned short T2020Recipient::GetPathNameCount () const
- {
- TPathName path;
- if ( fRecipient.GetPathName( path ) == false )
- {
- // The recipient doesn't 'have' a path name, so look up the path name
- // from the dNode and then stuff that path name into the recipient.
-
- TDirectory directory;
- if ( fRecipient.GetDirectory( directory ) &&
- fOwningLetter->GetHalfGateway()->FindPathNameForDNode ( fRecipient.GetNode(), directory, path ) )
- {
- ((T2020Recipient*) this)->fRecipient.SetPathName ( path );
- }
- }
-
- return path.GetNodeCount();
- }
-
- /***********************************|****************************************/
-
- void T2020Recipient::GetPathNameItem (unsigned short item, TRString& nodeName) const
- {
- if ( ( item > 0 ) && ( item <= GetPathNameCount () ) )
- {
- TPathName path;
- if ( fRecipient.GetPathName ( path ) )
- {
- path.GetNode ( item, nodeName );
- return;
- }
- }
-
- nodeName.SetLength( 0 ) ;
- nodeName.SetScript ( smRoman );
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::GetCID (CreationID& cid) const
- { TCreationID id;
-
- fRecipient.GetCreationID ( id );
- OCECopyCreationID ( id, & cid );
-
- return ((cid.source != 0) || (cid.seq != 0));
- }
-
- /***********************************|****************************************/
-
- OSType T2020Recipient::GetAddressType () const
- {
- if ( IsAddressTypePresent () )
- return fRecipient.GetExtensionType() ;
- else
- return kOCEInvalidDSSpec;
- }
-
- /***********************************|****************************************/
-
- typedef struct AOCEALANExtensionDataStruct {
- Str32 nbpName;
- Str32 nbpType;
- Str32 nbpZone;
- Str32 messageQueue;
- } AOCEALANExtensionDataStruct;
-
- /***********************************|****************************************/
-
- const StringPtr UnpackItem ( const void * & p )
- {
- const StringPtr result = (const StringPtr) p;
-
- p = ( const void*) ( ((char*) p ) + 1 + * ( unsigned char *) p );
-
- return result;
- }
-
- /***********************************|****************************************/
-
- inline void StringCopy ( StringPtr dest, StringPtr source, unsigned long maxLength )
- {
- if ( source[0] <= maxLength )
- BlockMove ( source, dest, 1 + source[0] );
- else
- dest[0] = 0;
- }
-
- /***********************************|****************************************/
-
- inline void StringCopyExclude ( StringPtr dest, StringPtr source, unsigned long maxLength, const StringPtr dontCopyIfSourceIsThisString )
- {
- dest[0] = 0;
- if ( source[0] <= maxLength )
- if ( ! EqualString ( source, dontCopyIfSourceIsThisString, false, false ) )
- BlockMove ( source, dest, 1 + source[0] );
- }
-
- /***********************************|****************************************/
-
- static void UnpackAOCEALANAddress ( const void * packedALANData, AOCEALANExtensionDataStruct& values )
- {
- StringCopy ( (StringPtr) & values.nbpName, UnpackItem ( packedALANData ), 31 );
- StringCopyExclude ( (StringPtr) & values.nbpType, UnpackItem ( packedALANData ), 31, "\pMsgReceiver" );
- StringCopy ( (StringPtr) & values.nbpZone, UnpackItem ( packedALANData ), 31 );
- StringCopyExclude ( (StringPtr) & values.messageQueue, UnpackItem ( packedALANData ), 31, "\pInMail_Queue" );
- }
-
- /***********************************|****************************************/
-
- unsigned long T2020Recipient::GetExtensionDataSize () const
- {
- switch ( GetAddressType() )
- {
- case 'alan':
- return sizeof ( AOCEALANExtensionDataStruct );
-
- case 'entn':
- return 0;
-
- default:
- return fRecipient.GetExtensionSize() - sizeof(ProtoRString);
- }
- }
-
- /***********************************|****************************************
- *
- * T2020Recipient::GetExtensionData()
- *
- * Return the extension data for this address. AOCE 'entn' addresses don't
- * have extension data. For most addresses, just return the extension data
- * ( minus the RString header part ). But, some addresses are going to
- * have to be special cased. Right now, the 'alan' address type will be
- * treated differently and will return a 'struct' of data which is a
- * packed NBP address followed by a pascal-style string.
- *
- ***********************************|****************************************/
-
- void T2020Recipient::GetExtensionData (unsigned long offset, void *buffer, unsigned long bufferSize) const
- {
- long dataSize = GetExtensionDataSize();
-
- if ((buffer) && (offset < dataSize))
- {
- switch ( GetAddressType() )
- {
- default:
- BlockMove ( (Ptr) ((char *) fRecipient.GetExtensionValue() + sizeof(ProtoRString) + offset),
- (Ptr) buffer, longmin( bufferSize, dataSize-offset ) );
- break;
-
- case 'entn':
- break;
-
- case 'alan': // Unpack the data into a AOCEALANExtensionDataStruct, then return it.
- { AOCEALANExtensionDataStruct extensionValue;
-
- UnpackAOCEALANAddress ( fRecipient.GetExtensionValue(), extensionValue );
-
-
- BlockMove ( (Ptr) ((char *) &extensionValue + offset),
- (Ptr) buffer, longmin( bufferSize, dataSize-offset ) );
- break;
- }
- }
- }
- }
-
- /***********************************|****************************************/
-
- ostream& T2020Recipient::DescribeSubclass(ostream& s) const
- {
- return s << "T2020Recipient: fOrigIndex=" << fOriginalRecipientIndex << " fRslvdIndex=" << fResolvedRecipientIndex << flush;
- }
-
- /***********************************|****************************************/
-
- ostream& T2020Recipient::operator >> ( ostream& s ) const
- {
- s << "T2020Recipient: ";
- if (this == nil)
- {
- s << "nil?" << flush;
- return s;
- }
-
- TRString name;
- if (GetRecipientName(name))
- s << name << " ";
- else
- { CreationID id;
-
- if (GetCID(id))
- s << id << " ";
- else
- {
- char extensionData[24];
- GetExtensionData(0, extensionData, sizeof(extensionData));
- s << "[" << extensionData << " " << OutputOSType(s, GetAddressType()) << "] ";
- }
- }
-
- s << " status=" << (short) GetStatus() << " ";
-
- s << "OrigIndex=" << (short) fOriginalRecipientIndex << " ";
- s << "RslvdIndex=" << (short) fResolvedRecipientIndex << " " << flush;
-
- return s;
- }
-
- /***********************************|****************************************/
-
- unsigned short T2020Recipient::GetOriginalRecipientIndex () const
- {
- return fOriginalRecipientIndex;
- }
-
- /***********************************|****************************************/
-
- void T2020Recipient::SetOriginalRecipientIndex (unsigned short index)
- {
- fOriginalRecipientIndex = index;
- }
-
- /***********************************|****************************************/
-
- unsigned short T2020Recipient::GetResolvedRecipientIndex () const
- {
- return fResolvedRecipientIndex;
- }
-
- /***********************************|****************************************/
-
- void T2020Recipient::SetResolvedRecipientIndex (unsigned short index)
- {
- fResolvedRecipientIndex = index;
- }
-
- /***********************************|****************************************/
-
- void T2020Recipient::SetResponsible (Boolean responsible)
- {
- fResponsible = responsible;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::GetHidden () const
- {
- return fHidden;
- }
-
- /***********************************|****************************************/
-
- void T2020Recipient::SetHidden (Boolean hidden)
- {
- fHidden = hidden;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::GetOCERecipient(OCERecipient& oceRecipient) const
- {
- BlockMove ( (Ptr) ((const OCERecipient*) fRecipient), (Ptr) & oceRecipient, sizeof ( oceRecipient ) );
- return true;
- }
-
- /***********************************|****************************************/
-
- Boolean
- T2020Recipient::SetStatus ( RecipientStatusSet status )
- {
- // If we're setting the recipient to any status other than unknown, then
- // also mark the recipient as 'done' back to AOCE. This will prevent AOCE
- // from telling us that we are responsible for this recipient should the
- // gateway crash after this operation but before the letter has been
- // completely sent.
- if ((status != cUnknown) && (status != fStatus) && ( GetResponsible() == true ) ) {
- fOwningLetter->MarkRecipient(this);
- }
- fStatus = status;
-
- return true;
- }
-
- /***********************************|****************************************/
-
- RecipientStatusSet
- T2020Recipient::GetStatus () const
- {
- return fStatus;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::IsPathInfoPresent () const
- {
- return true; // OCERecipients always have path information
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::IsPathInfoOptional () const
- {
- #if 1
- if ( ! fCheckedWhetherPathInformationIsOptional )
- {
- ((T2020Recipient*)this)->fIsPathInfoOptional = false;
-
- // If the user is in the "Users & Groups" cluster, then the path information
- // might be optional -- only if there aren't any other recipients with the
- // same name in the "Users & Groups" cluster.
- unsigned long recipientDNode;
- if ( GetPathDNode ( recipientDNode ) )
- {
- TRString recipientName, recipientType;
-
- if ( GetRecipientName ( recipientName ) && GetRecipientType ( recipientType ) )
- { TRLI usersAndGroupsCluster ( fOwningLetter->GetHalfGateway()->GetAOCEDirectory(), 3 );
- TRecordID foundAddress;
-
- unsigned long numberOfAddressesWithThisName = fOwningLetter->GetHalfGateway()->FindADASAddresses ( recipientName, recipientType, usersAndGroupsCluster, foundAddress, 2 );
-
- if ( numberOfAddressesWithThisName == 1 )
- ((T2020Recipient*)this)->fIsPathInfoOptional = true;
- }
- }
-
- ((T2020Recipient*)this)->fCheckedWhetherPathInformationIsOptional = true;
- }
-
- return fIsPathInfoOptional;
-
- #else
-
- return false; // eventually, change this.
-
- #endif
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::IsNameAndPathUnique () const
- {
- // Check whether this recipient name is unique in it's cluster. If it isn't, then
- // act like this recipient doesn't have a 'name', since the name/path information
- // won't be unique.
- if ( ! fCheckedWhetherRecipientNameIsUnique )
- { unsigned long recipientDNode;
-
- if ( GetPathDNode ( recipientDNode ) )
- {
- TRLI userClusterRecord ( fOwningLetter->GetHalfGateway()->GetAOCEDirectory(), recipientDNode );
- TRecordID foundAddress;
-
- unsigned long numberOfAddressesWithThisName =
- fOwningLetter->GetHalfGateway()->FindADASAddresses ( ((const DSSpec*) fRecipient)->entitySpecifier->local.recordName,
- ((const DSSpec*) fRecipient)->entitySpecifier->local.recordType,
- userClusterRecord, foundAddress, 2 );
-
- ((T2020Recipient *) this)->fCheckedWhetherRecipientNameIsUnique = true;
- ((T2020Recipient *) this)->fRecipientNameIsUnique = ( numberOfAddressesWithThisName <= 1 );
- }
- else
- {
- // Got an error; assume the name is unique ( almost always will be ) and go on.
- ((T2020Recipient *) this)->fCheckedWhetherPathInformationIsOptional = false;
- ((T2020Recipient *) this)->fRecipientNameIsUnique = true;
- }
- }
-
- return fRecipientNameIsUnique;
- }
-
- /***********************************|****************************************/
-
- Boolean T2020Recipient::IsAddressTypePresent () const
- {
- return fRecipient.GetExtensionType() != kOCEentnDSSpec;
- }
-
- /***********************************|****************************************/
-
-